package org.yelongframework.qrcode.impl.zxing;

import java.awt.image.BufferedImage;

import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.common.BitMatrix;

/**
 * {@link BitMatrix}转换为 {@link BufferedImage} 工具类
 * 
 * @since 1.0.0
 */
public final class MatrixToImageUtils {

	private MatrixToImageUtils() {
	}

	/**
	 * 转换为{@link BufferedImage}并去除白边
	 * 
	 * @param matrix matrix
	 * @return 去除白边的{@link BufferedImage}
	 */
	public static BufferedImage toBufferedImageRemoveWhiteBorder(BitMatrix matrix) {
		int[] rec = matrix.getEnclosingRectangle();
		int resWidth = rec[2] + 1;
		int resHeight = rec[3] + 1;

		BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
		resMatrix.clear();
		for (int i = 0; i < resWidth; i++) {
			for (int j = 0; j < resHeight; j++) {
				if (matrix.get(i + rec[0], j + rec[1]))
					resMatrix.set(i, j);
			}
		}

		int width = resMatrix.getWidth();
		int height = resMatrix.getHeight();
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				image.setRGB(x, y, resMatrix.get(x, y) ? MatrixToImageConfig.BLACK : MatrixToImageConfig.WHITE);
			}
		}
		return image;
	}

	/**
	 * 转换为{@link BufferedImage}并去除白边并设置外边距（及自己定义二维码的白边）
	 * 
	 * @param matrix matrix
	 * @return 固定外边距的{@link BufferedImage}
	 */
	public static BufferedImage toBufferedImageRemoveWhiteBorderSetMargin(BitMatrix matrix, int margin) {
		if (margin < 0) {
			throw new IllegalArgumentException("外边距不能小于0");
		}
		int[] rec = matrix.getEnclosingRectangle();
		int resWidth = rec[2] + 1;
		int resHeight = rec[3] + 1;

		BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
		resMatrix.clear();
		for (int i = 0; i < resWidth; i++) {
			for (int j = 0; j < resHeight; j++) {
				if (matrix.get(i + rec[0], j + rec[1]))
					resMatrix.set(i, j);
			}
		}

		// 宽高各自添加边距
		int width = resMatrix.getWidth() + margin * 2;
		int height = resMatrix.getHeight() + margin * 2;
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				// 如果是边距直接设置白
				if (isMargin(width, margin, x + 1) || isMargin(height, margin, y + 1)) {
					image.setRGB(x, y, MatrixToImageConfig.WHITE);
				} else {
					image.setRGB(x, y, resMatrix.get(x - margin, y - margin) ? MatrixToImageConfig.BLACK
							: MatrixToImageConfig.WHITE);
				}
			}
		}
		return image;
	}

	/**
	 * 是否是外边距
	 * 
	 * @param length      长度
	 * @param margin      外边距长度
	 * @param verifyIndex 当前需要验证的索引
	 * @return <code>true</code>指定的索引是外边距
	 */
	private static boolean isMargin(int length, int margin, int verifyIndex) {
		if (margin <= 0) {
			return false;
		}
		if (length < 0 || verifyIndex < 0) {
			throw new IllegalArgumentException("length or verifyIndex不能小于0");
		}
		if (verifyIndex > length) {
			throw new IllegalArgumentException("验证的索引不能大于总长度");
		}
		if (verifyIndex <= margin) {
			return true;
		}
		if (verifyIndex >= length - margin + 1) {
			return true;
		}
		return false;
	}

}
